package client

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/unknwon/com"
	"gorm.io/gorm"
	"likeadmin/admin/schemas/req"
	"likeadmin/admin/schemas/resp"
	"likeadmin/config"
	"likeadmin/core/request"
	"likeadmin/core/response"
	"likeadmin/model/client" // 添加此导入以引用 Orders 模型
	"likeadmin/util"
	"strings"
	"time"
)

type IOrdersService interface {
	List(c *gin.Context, page request.PageReq, listReq req.OrdersListReq) (res response.PageResp, e error)
	Detail(id uint) (res resp.OrdersResp, e error)
	CallBack(id uint) (res resp.OrdersResp, e error)
	Statistic(c *gin.Context, listReq req.OrdersListReq) (res map[string]any, e error)
	AdData(c *gin.Context, adDataReq req.AdDataReq) (res response.PageResp, e error)
}

// NewOrdersService 初始化
func NewOrdersService(db *gorm.DB) IOrdersService {
	return &ordersService{db: db}
}

// ordersService 订单服务实现类
type ordersService struct {
	db *gorm.DB
}

// List 订单列表
func (srv ordersService) List(c *gin.Context, page request.PageReq, listReq req.OrdersListReq) (res response.PageResp, e error) {
	// 分页信息
	limit := page.PageSize
	offset := page.PageSize * (page.PageNo - 1)
	// 查询
	model := srv.db.Model(&client.Orders{}) // 使用完整包路径

	adminId := config.AdminConfig.GetAdminId(c)
	if adminId != 1 {
		model = model.Where("creater_id = ?", adminId)
	}

	if listReq.Uid > 0 {
		model = model.Where("uid = ?", listReq.Uid)
	}
	if listReq.Type >= 0 {
		model = model.Where("type = ?", listReq.Type)
	}
	if listReq.OutNo != "" {
		model = model.Where("out_no = ?", listReq.OutNo)
	}
	if listReq.IsPay >= 0 {
		model = model.Where("is_pay = ?", listReq.IsPay)
	}
	if listReq.DramaId != "" {
		model = model.Where("drama_id = ?", listReq.DramaId)
	}
	if listReq.SourceId != "" {
		model = model.Where("source_id = ?", listReq.SourceId)
	}
	if listReq.AccountId != "" {
		model = model.Where("account_id = ?", listReq.AccountId)
	}

	if listReq.CallbackStatus >= 0 {
		model = model.Where("callback_status = ?", listReq.CallbackStatus)
	}

	if !listReq.StartTime.IsZero() {
		model = model.Where("create_time >= ?", listReq.StartTime.Unix())
	}
	if !listReq.EndTime.IsZero() {
		model = model.Where("create_time <= ?", listReq.EndTime.Unix()+(3600*24-1))
	}

	if listReq.ProjectId != "" {
		model = model.Where("project_id = ?", listReq.ProjectId)
	}

	if listReq.PromotionId != "" {
		model = model.Where("promotion_id = ?", listReq.PromotionId)
	}

	// 总数
	var count int64
	err := model.Count(&count).Error
	if e = response.CheckErr(err, "List Count err"); e != nil {
		return
	}
	// 数据
	var objs []client.Orders // 使用完整包路径
	err = model.Limit(limit).Offset(offset).Order("id desc").Find(&objs).Error
	if e = response.CheckErr(err, "List Find err"); e != nil {
		return
	}

	resps := []resp.OrdersResp{} // 确保 OrdersResp 已定义
	response.Copy(&resps, objs)

	return response.PageResp{
		PageNo:   page.PageNo,
		PageSize: page.PageSize,
		Count:    count,
		Lists:    resps,
	}, nil
}

// Detail 订单详情
func (srv ordersService) Detail(id uint) (res resp.OrdersResp, e error) { // 确保 OrdersResp 已定义
	var obj client.Orders // 使用完整包路径
	err := srv.db.Where("id = ?", id).Limit(1).First(&obj).Error
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Detail First err"); e != nil {
		return
	}
	response.Copy(&res, obj)
	return
}

// CallBack 订单回传
func (srv ordersService) CallBack(id uint) (res resp.OrdersResp, e error) {
	// 开启事务
	tx := srv.db.Begin()
	defer func() {
		if r := recover(); r != nil || e != nil {
			tx.Rollback()
		}
	}()

	var order client.Orders
	err := tx.Where("id = ? AND is_pay = ? AND callback_status = ?", id, 1, 0).Limit(1).First(&order).Error
	// 校验
	if e = response.CheckErrDBNotRecord(err, "不允许回传!"); e != nil {
		return
	}

	response.Copy(&res, order)

	// 查询回调信息
	var callbackInfo client.CallbackInfo
	err = tx.Where("id = ?", order.CallbackInfoId).Order("id desc").Limit(1).First(&callbackInfo).Error
	if e = response.CheckErrDBNotRecord(err, "callbackInfo First err"); e != nil {
		return
	}

	// 解析链接数据为对象
	var reportData map[string]interface{}
	err = util.ToolsUtil.JsonToObj(callbackInfo.Link, &reportData)
	if err != nil {
		e = response.CheckErr(err, "回调数据解析失败")
		return
	}

	// 检查解析结果
	if reportData == nil {
		e = response.AssertArgumentError.Make("回调数据解析结果为空")
		return
	}

	// 应用渠道: 1=头条, 2=百度, 3=uc, 4=oppo, 5=vivo, 6=快手
	if callbackInfo.Channel == 1 {
		var resultLink map[string]interface{}
		json.Unmarshal([]byte(callbackInfo.Link), &resultLink)
		// 回传上报
		result, _ := util.OceanengineCallbackUtil{}.Callback(&util.AdCallback{
			CallbackURL:     reportData["callback_url"].(string),
			Action:          "PAY",
			MicroCreateTime: callbackInfo.CreateTime * 1000, // 转换为毫秒
			Money:           order.Money,
		})

		// 检查上报结果
		if strings.Contains(result, "::error") {
			e = response.CheckErr(fmt.Errorf("upload failed"), "更新回调状态失败:id=%d", reportData["id"])
			return
		}

	}
	if callbackInfo.Channel == 4 {
		reportData["id"] = com.ToStr(callbackInfo.ID)
		reportData["dataType"] = 16
		reportData["package_name"] = order.PackageName

		// 回传上报
		result := util.OppoCallbackUtil{}.UploadOppo(reportData)

		// 检查上报结果
		if strings.Contains(result, "::error") {
			e = response.CheckErr(fmt.Errorf("upload failed"), "更新回调状态失败:id=%d", reportData["id"])
			return
		}
	}

	// 更新回调状态
	callbackInfo.CallbackStatus = 2
	callbackInfo.UpdateTime = time.Now().Unix()

	err = tx.Save(&callbackInfo).Error
	if e = response.CheckErr(err, "保存回调信息失败"); e != nil {
		return
	}

	// 更新订单回调状态
	err = tx.Model(&order).Updates(map[string]interface{}{"callback_status": 1}).Error
	if e = response.CheckErr(err, "更新订单回调状态失败"); e != nil {
		return
	}

	// 提交事务
	err = tx.Commit().Error
	if e = response.CheckErr(err, "提交事务失败"); e != nil {
		return
	}

	return res, nil
}
func (srv ordersService) Statistic(c *gin.Context, listReq req.OrdersListReq) (res map[string]any, e error) {
	statistic := map[string]any{
		"money_pay":    0, // 已支付金额
		"money_total":  0, // 预提单总金额
		"order_pay":    0, // 订单成功数量
		"order_total":  0, // 预提单数量
		"callback_num": 0, // 已回传总数
	}

	model := srv.db.Model(&client.Orders{})

	adminId := config.AdminConfig.GetAdminId(c)
	if adminId != 1 {
		model = model.Where("creater_id = ?", adminId)
	}

	if listReq.Uid > 0 {
		model = model.Where("uid = ?", listReq.Uid)
	}
	if listReq.Type >= 0 {
		model = model.Where("type = ?", listReq.Type)
	}
	if listReq.OutNo != "" {
		model = model.Where("out_no = ?", listReq.OutNo)
	}
	if listReq.IsPay >= 0 {
		model = model.Where("is_pay = ?", listReq.IsPay)
	}
	if listReq.DramaId != "" {
		model = model.Where("drama_id = ?", listReq.DramaId)
	}
	if listReq.SourceId != "" {
		model = model.Where("source_id = ?", listReq.SourceId)
	}
	if listReq.AccountId != "" {
		model = model.Where("account_id = ?", listReq.AccountId)
	}
	if listReq.ProjectId != "" {
		model = model.Where("project_id = ?", listReq.ProjectId)
	}
	if listReq.PromotionId != "" {
		model = model.Where("promotion_id = ?", listReq.PromotionId)
	}
	if listReq.CallbackStatus >= 0 {
		model = model.Where("callback_status = ?", listReq.CallbackStatus)
	}

	if !listReq.StartTime.IsZero() {
		model = model.Where("create_time >= ?", listReq.StartTime.Unix())
	}
	if !listReq.EndTime.IsZero() {
		model = model.Where("create_time <= ?", listReq.EndTime.Unix()+(3600*24-1))
	}

	model = model.Where("delete_time = ?", 0)

	// 统计总订单数量
	var orderTotal int64
	if err := model.Count(&orderTotal).Error; err != nil {
		return statistic, fmt.Errorf("统计总订单数量失败: %w", err)
	}
	statistic["order_total"] = uint(orderTotal)

	// 统计预提单总金额
	var moneyTotal uint
	if err := model.Select("IFNULL(SUM(money), 0)").Scan(&moneyTotal).Error; err != nil {
		return statistic, fmt.Errorf("统计预提单总金额失败: %w", err)
	}
	// 转换为元并保留两位小数
	moneyTotalFloat := float64(moneyTotal) / 100.0
	statistic["money_total"] = fmt.Sprintf("%.2f", moneyTotalFloat)

	// 统计已支付订单数量和金额 - 分开查询避免 Scan 参数错误
	var orderPayCount int64
	if err := model.Where("is_pay = ?", 1).Count(&orderPayCount).Error; err != nil {
		return statistic, fmt.Errorf("统计已支付订单数量失败: %w", err)
	}
	statistic["order_pay"] = uint(orderPayCount)

	var moneyPay uint
	if err := model.Where("is_pay = ?", 1).Select("IFNULL(SUM(money), 0)").Scan(&moneyPay).Error; err != nil {
		return statistic, fmt.Errorf("统计已支付订单金额失败: %w", err)
	}
	moneyPayFloat := float64(moneyPay) / 100.0
	statistic["money_pay"] = fmt.Sprintf("%.2f", moneyPayFloat)

	// 统计已回传数量
	var callbackNum int64
	if err := model.Where("callback_status = ?", 1).Count(&callbackNum).Error; err != nil {
		return statistic, fmt.Errorf("统计回传数量失败: %w", err)
	}
	statistic["callback_num"] = uint(callbackNum)

	return statistic, nil
}

func (srv ordersService) AdData(c *gin.Context, adDataReq req.AdDataReq) (res response.PageResp, e error) {

	// 查询
	model := srv.db.Model(&client.Orders{}) // 使用完整包路径

	adminId := config.AdminConfig.GetAdminId(c)
	if adminId != 1 {
		model = model.Where("creater_id = ?", adminId)
	}

	now := time.Now()
	todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	todayTime := todayStart.Unix()

	model.Where("is_pay= ? AND create_time > ?", 1, todayTime)

	var count int64
	var objs []client.Orders // 使用完整包路径

	if adDataReq.Type == "promotion_id" {
		model.Where("promotion_id != ? AND promotion_id != ?", "", "__PROMOTION_ID__")
		// 总数
		err := model.Group("promotion_id").Count(&count).Error
		if e = response.CheckErr(err, "AdData Count err"); e != nil {
			return
		}
		err = model.Group("promotion_id").Select("promotion_id", "promotion_name").Order("promotion_id desc").Find(&objs).Error
		if e = response.CheckErr(err, "AdData Find err"); e != nil {
			return
		}

	} else {
		model.Where("project_id != ? AND project_id != ?", "", "__PROJECT_ID__")
		err := model.Group("project_id").Count(&count).Error
		if e = response.CheckErr(err, "AdData Count err"); e != nil {
			return
		}
		// 数据
		err = model.Group("project_id").Select("project_id", "project_name").Order("project_id desc").Find(&objs).Error
		if e = response.CheckErr(err, "AdData Find err"); e != nil {
			return
		}

	}

	resps := []resp.AdDataResp{}

	for _, i2 := range objs {
		if adDataReq.Type == "promotion_id" {
			resps = append(resps, resp.AdDataResp{
				Label: i2.PromotionId + " " + i2.PromotionName,
				Value: i2.PromotionId,
			})
		} else {
			resps = append(resps, resp.AdDataResp{
				Label: i2.ProjectId + " " + i2.ProjectName,
				Value: i2.ProjectId,
			})
		}

	}

	return response.PageResp{
		Count: count,
		Lists: resps,
	}, nil
}
